# [九] Bean的实例化-Bean的销毁

Bean的销毁

bean创建完成后就会对这个 bean注册一个销毁的 DisposableBeanAdapter对象,Spring中就是通过DisposableBeanAdapter类负责bean的销毁过工作。

# Bean的销毁入口

  • ├─ getBean
  • │ ├─ doGetBean
  • │ │ ├─ getSingleton
  • │ │ ├─ getObjectForBeanInstance
  • │ │ ├─ getSingletond
  • │ │ │ ├─ beforeSingletonCreation
  • │ │ │ ├─ createBean
  • │ │ │ │ ├─ doCreateBean
  • │ │ │ │ │ ├─ createBeanInstance
  • │ │ │ │ │ ├─ applyMergedBeanDefinitionPostProcessors
  • │ │ │ │ │ ├─ earlySingletonExposure
  • │ │ │ │ │ ├─ addSingletonFactory
  • │ │ │ │ │ ├─ populateBean
  • │ │ │ │ │ ├─ initializeBean
  • │ │ │ │ │ └─ registerDisposableBeanIfNecessary ① bean 的销毁过程入口
  • │ │ │ ├─ afterSingletonCreation
  • │ │ │ └─ addSingleton

# Bean的销毁过程解析

首先我们来看一下① Bean的销毁过程:

进入 doCreateBean () 方法

类文件: org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory

try {
	... 
	
	//注册bean销毁时的类DisposableBeanAdapter
	registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
	throw new BeanCreationException(
		mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}

进入 registerDisposableBeanIfNecessary () 方法

类文件: org.springframework.beans.factory.support.AbstractBeanFactory

protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
		AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
		if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
			// 如果是单例 bean
			if (mbd.isSingleton()) {
				// 对这个bean注册一个销毁的Adapter对象,对给定的bean执行销毁工作
				// 过滤了 DestructionAwareBeanPostProcessor 类型的接口
				registerDisposableBean(beanName,
						new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
			}
			else {
				// 拿到bean的作用域
				Scope scope = this.scopes.get(mbd.getScope());
				if (scope == null) {
					throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
				}
				scope.registerDestructionCallback(beanName,
						new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
			}
		}
	}

# Bean销毁的核心类

在 bean创建完成后就会对这个 bean注册一个销毁的 DisposableBeanAdapter对象,这个类就是 销毁的核心类DisposableBeanAdapter就是负责bean销毁的类。在这个类中收集了该bean 是否实现了 DisposableBean接口,是否配置 destroy-method属性,如果有则 执行其destroy() 方法。

问题

① Bean的销毁过程是什么时候触发的呢?

答案

  • 1、在Spring 中执行显式关闭上下文,关闭时候会执行实现DisposableBean接口类中的destroy() 方法,如:
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"spring.xml"});
// 以下两种显式关闭都会调用实现了DisposableBean接口类中的destroy() 方法
// 1、显式关闭上下文
context.close();
// 2、显式关闭上下文
context.registerShutdownHook();
  • 2、在Web环境中,当Tomcat关闭的时候就会调用到 servlet中的销毁方法,在这个方法中就会最终也会掉用到Spring中 DisposableBeanAdapter类的destroy()方法,该方法就会根据前面的收集进行调用。

# servlet中的销毁方法

public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
    public ContextLoaderListener() {
    }

    public ContextLoaderListener(WebApplicationContext context) {
        super(context);
    }

    public void contextInitialized(ServletContextEvent event) {
        this.initWebApplicationContext(event.getServletContext());
    }
	//  servlet中的销毁方法
    public void contextDestroyed(ServletContextEvent event) {
       // 该方法最终会调用Spring的DisposableBeanAdapter类的destroy()
        this.closeWebApplicationContext(event.getServletContext());
        ContextCleanupListener.cleanupAttributes(event.getServletContext());
    }
}

servlet中的closeWebApplicationContext方法最终也会掉用到Spring中的DisposableBeanAdapter类的destroy()方法,该方法就会根据前面的收集进行调用。